/**
 * ChatInterface Component Tests
 * Property-based tests for chat interface behavior
 */

import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import fc from 'fast-check';
import { ChatInterface } from './ChatInterface';

describe('ChatInterface', () => {
  /**
   * **Feature: emotion-3d-website, Property 3: Chat Submission Triggers Analysis**
   * **Validates: Requirements 2.2**
   * 
   * For any non-empty text input submitted through the chat interface,
   * the emotion analysis service SHALL be called with that exact text.
   */
  it('should call onSubmit with exact text for any non-empty input', async () => {
    await fc.assert(
      fc.asyncProperty(
        // Generate non-empty strings with at least one non-whitespace character
        fc.string({ minLength: 1 }).filter(s => s.trim().length > 0),
        async (inputText) => {
          const mockOnSubmit = vi.fn().mockResolvedValue(undefined);
          
          const { container } = render(
            <ChatInterface onSubmit={mockOnSubmit} isLoading={false} />
          );
          
          const textarea = container.querySelector('textarea');
          expect(textarea).toBeTruthy();
          
          // Simulate user input
          fireEvent.change(textarea!, { target: { value: inputText } });
          
          // Submit the form
          const form = container.querySelector('form');
          fireEvent.submit(form!);
          
          // Wait for async operations
          await waitFor(() => {
            expect(mockOnSubmit).toHaveBeenCalledTimes(1);
          });
          
          // Verify the exact trimmed text was passed
          expect(mockOnSubmit).toHaveBeenCalledWith(inputText.trim());
        }
      ),
      { numRuns: 100 }
    );
  });

  /**
   * **Feature: emotion-3d-website, Property 4: Empty Input Rejection**
   * **Validates: Requirements 2.3**
   * 
   * For any string composed entirely of whitespace or empty string,
   * submitting it through the chat interface SHALL be rejected and
   * the submission callback SHALL NOT be invoked.
   */
  it('should reject empty or whitespace-only inputs without calling onSubmit', async () => {
    await fc.assert(
      fc.asyncProperty(
        // Generate strings that are either empty or contain only whitespace
        fc.oneof(
          fc.constant(''),
          fc.stringOf(fc.constantFrom(' ', '\t', '\n', '\r'), { minLength: 1, maxLength: 20 })
        ),
        async (emptyInput) => {
          const mockOnSubmit = vi.fn().mockResolvedValue(undefined);
          
          const { container } = render(
            <ChatInterface onSubmit={mockOnSubmit} isLoading={false} />
          );
          
          const textarea = container.querySelector('textarea');
          expect(textarea).toBeTruthy();
          
          // Simulate user input
          fireEvent.change(textarea!, { target: { value: emptyInput } });
          
          // Submit the form
          const form = container.querySelector('form');
          fireEvent.submit(form!);
          
          // Verify onSubmit was NOT called (synchronous check since validation is immediate)
          expect(mockOnSubmit).not.toHaveBeenCalled();
        }
      ),
      { numRuns: 100 }
    );
  });

  /**
   * **Feature: emotion-3d-website, Property 5: Input Clearing After Submission**
   * **Validates: Requirements 2.5**
   * 
   * For any successful form submission, the input field SHALL be cleared
   * (empty string) after the response is received.
   */
  it('should clear input field after successful submission', async () => {
    await fc.assert(
      fc.asyncProperty(
        fc.string({ minLength: 1 }).filter(s => s.trim().length > 0),
        async (inputText) => {
          const mockOnSubmit = vi.fn().mockResolvedValue(undefined);
          
          const { container } = render(
            <ChatInterface onSubmit={mockOnSubmit} isLoading={false} />
          );
          
          const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
          expect(textarea).toBeTruthy();
          
          // Simulate user input
          fireEvent.change(textarea, { target: { value: inputText } });
          expect(textarea.value).toBe(inputText);
          
          // Submit the form
          const form = container.querySelector('form');
          fireEvent.submit(form!);
          
          // Wait for the submission to complete
          await waitFor(() => {
            expect(mockOnSubmit).toHaveBeenCalled();
          });
          
          // Wait for state update
          await waitFor(() => {
            expect(textarea.value).toBe('');
          });
        }
      ),
      { numRuns: 100 }
    );
  });
});
